module UI where

import Core
import System.Exit

readLine = do
              s <- getLine
              return (s)

readCellValue = do
                   s <- getLine
                   return s

readNumber = do 
                s <- readLine   
                if (isNumber s) == False then
                  do
                     putStrLn "The entered value must be integer. Please try again: "
                     result <- readNumber
                     return (result)
                else             
                  return (read s)
                   
readPositiveNumber = do
                       num <- readNumber
                       if num <= 0 then
                         do
                           putStrLn "The entered value must be positive integer. Please try again: "
                           result <- readPositiveNumber
                           return (result)
                       else
                         return (num)
                         
readMaxNumber maxVal = do
                         num <- readPositiveNumber
                         
                         if num > maxVal then
                           do
                             putStrLn ("The entered value must be smaller than " ++ (show maxVal) ++ "'. Please try again: ")
                             result <- readMaxNumber maxVal
                             return (result)
                         else                          
                           return (num)
                           
readMaxMinNumber minVal maxVal = do
                                    num <- readMaxNumber maxVal
                         
                                    if num < minVal then
                                      do
                                         putStrLn ("The entered value must be between '" ++ (show minVal) ++ "' and '" ++ (show maxVal) ++ "'. Please try again: ")
                                         result <- readMaxNumber maxVal
                                         return (result)
                                    else                          
                                      return (num)                           

createNewSpreadsheet = do 
                          putStrLn "Enter the number of rows: "
                          rows <- readPositiveNumber
                          putStrLn "Enter the number of columns: "
                          cols <- readPositiveNumber
                          return (initSpreadSheet rows cols)

displayColumnHeaders cols = do 
                               return (0)

formatCell Empty _ = ""
formatCell (Text val) _ = show val
formatCell (Number val) _ = show val
formatCell (Sum cells) spreadsheet = show (sumAll spreadsheet cells)
formatCell (Prod cells) spreadsheet = show (multiplyAll spreadsheet cells)
formatCell (Avg cells) spreadsheet = show (avgAll spreadsheet cells)

displayRow [] _ = do
                     putStr "|"
                     return (0)
                   
displayRow (c:cs) spreadsheet = do
                                   putStr ("|" ++ (formatCell c spreadsheet) ++ "\t")
                                   displayRow cs spreadsheet

displayRows [] _ = do 
                      return (0)
                    
displayRows (r:rs) spreadsheet = do                         
                                    displayRow r spreadsheet
                                    putStrLn ""
                                    displayRows rs spreadsheet
                                                                  
displaySpreadsheet spreadsheet = do 
                                    displayColumnHeaders (getCols spreadsheet)
                                    displayRows spreadsheet spreadsheet
                                    return (spreadsheet)

saveSpreadsheet spreadsheet = do
                                 putStrLn "Enter file name: "
                                 fileName <- readLine
                                 writeSpreadsheetToFile fileName spreadsheet
                                 return (spreadsheet)

loadSpreadsheet = do 
                     putStrLn "Enter file name: "
                     fileName <- readLine
                     result <- readSpreadsheetFromFile $! fileName
                     return (result)        
        
insertRowToSpreadsheet spreadsheet = do 
                                     putStrLn "Enter the index of the row before which you want to insert a new one:"
                                     newRowIndex <- readMaxNumber (getRows spreadsheet)
                                     return (addRow spreadsheet (newRowIndex - 1) (getCols spreadsheet))
                                     
addRowToSpreadsheet spreadsheet = do
                                     return (addRow spreadsheet (getRows spreadsheet) (getCols spreadsheet)) 
                                                            
deleteRowFromSpreadsheet spreadsheet = do 
                                          putStrLn "Enter the index of the row before to be deleted:"
                                          rowToBeDeletedIndex <- readMaxNumber (getRows spreadsheet)
                                          return (deleteRow spreadsheet (rowToBeDeletedIndex - 1))
                  
insertColumnToSpreadsheet spreadsheet = do 
                                           putStrLn "Enter the index of the column before which you want to insert a new one:"
                                           newColumnIndex <- readMaxNumber (getCols spreadsheet)
                                           return (insertColumn spreadsheet (newColumnIndex - 1))

addColumnToSpreadsheet spreadsheet = do 
                                        return (insertColumn spreadsheet (getCols spreadsheet))
                                       
deleteColumnFromSpreadsheet spreadsheet = do 
                                             putStrLn "Enter the index of the column before to be deleted:"
                                             columnToBeDeletedIndex <- readMaxNumber (getCols spreadsheet)
                                             return (deleteColumn spreadsheet (columnToBeDeletedIndex - 1))

modifySpreadsheet spreadsheet = do
                                   displayModifySpreadsheetMenu 
                                   decision <- readNumber
                                   
                                   if decision == 1 then
                                     do
                                       result <- insertRowToSpreadsheet spreadsheet
                                       return (result)
                                   else if decision == 2 then
                                     do
                                       result <- addRowToSpreadsheet spreadsheet
                                       return (result)  
                                   else if decision == 3 then
                                     do
                                        result <- deleteRowFromSpreadsheet spreadsheet
                                        return (result)
                                   else if decision == 4 then
                                     do
                                        result <- insertColumnToSpreadsheet spreadsheet
                                        return (result)
                                   else if decision == 5 then
                                     do
                                        result <- addColumnToSpreadsheet spreadsheet
                                        return (result)
                                   else if decision == 6 then
                                     do
                                        result <- deleteColumnFromSpreadsheet spreadsheet
                                        return (result)                          
                                   else if decision == 0 then
                                     do
                                        return (spreadsheet)
                                   else
                                     do
                                        putStrLn "Incorrect option."
                                        return (spreadsheet)
                                                                                                           
displayModifySpreadsheetMenu = do 
                                  putStrLn "Please choose one of allowable options:"
                                  putStrLn "1 - Insert row"
                                  putStrLn "2 - Add row at end"
                                  putStrLn "3 - Delete row"
                                  putStrLn "4 - Insert column"
                                  putStrLn "5 - Add column at end"
                                  putStrLn "6 - Delete column"
                                  putStrLn "0 - Cancel"


insertSimpleValueIntoSpreadsheet spreadsheet = do 
                                                 putStrLn "Enter the row index: "
                                                 row <- readMaxNumber (getRows spreadsheet)
                                                 putStrLn "Enter the column index: "
                                                 col <- readMaxNumber (getCols spreadsheet)
                                                 putStrLn "Enter the value: "
                                                 val <- readCellValue
                                                 if isReal val then
                                                   do
                                                      let num = (read val) 
                                                      let cellVal = Number num                                                     
                                                      return (insertValue spreadsheet (row - 1) (col - 1) cellVal)
                                                 else
                                                   do 
                                                      let cellVal = Text val                                                      
                                                      return (insertValue spreadsheet (row - 1) (col - 1) cellVal)

readFunCellsRangeMenu = do
                           putStrLn "Please choose one of allowable options:"
                           putStrLn "1 - Insert cells range"
                           putStrLn "2 - Insert cells list"
                           putStrLn "0 - Cancel"

readFunCellsRange spreadsheet = do
                                   putStrLn "Enter begining row index: "
                                   row1 <- readMaxNumber (getRows spreadsheet)
                                   putStrLn "Enter begining column index: "
                                   col1 <- readMaxNumber (getCols spreadsheet)
                                       
                                   putStrLn "Enter ending row index: "
                                   row2 <- readMaxMinNumber row1 (getRows spreadsheet)
                                   putStrLn "Enter ending column index: "
                                   col2 <- readMaxMinNumber col1 (getCols spreadsheet)
                                       
                                   return (cellRangeToList [(row1 - 1, col1 - 1), (row2 - 1, col2 - 1)])
                       
readFunCellsList spreadsheet = do
                                  putStrLn "Enter the row index: "
                                  row <- readMaxNumber (getRows spreadsheet)
                                  putStrLn "Enter the column index: "
                                  col <- readMaxNumber (getCols spreadsheet)
                                  let tuple = (row - 1, col - 1)
                                  putStrLn "Continue? [y | n]:"                                  
                                  decision <- getLine
                                  if ((decision == "y") || (decision == "Y")) then
                                    do                                       
                                       rest <- readFunCellsList spreadsheet
                                       return (tuple : rest)
                                  else 
                                    return ([tuple])

readFunCells spreadsheet = do          
                              readFunCellsRangeMenu
                              decision <- readNumber
                                       
                              if decision == 1 then
                                do
                                   result <- readFunCellsRange spreadsheet
                                   return (result)
                              else if decision == 2 then
                                do
                                   result <- readFunCellsList spreadsheet
                                   return (result)   
                              else if decision == 0 then
                                do
                                   return ([])
                              else
                                do
                                   putStrLn "Incorrect option."
                                   return ([])
                                                      
insertFunIntoSpreadsheetMenu = do
                                  putStrLn "Please choose one of allowable options:"
                                  putStrLn "1 - Sum"
                                  putStrLn "2 - Prod"
                                  putStrLn "3 - Avg"
                                  putStrLn "0 - Cancel"

insertFunIntoSpreadsheet spreadsheet = do
                                          insertFunIntoSpreadsheetMenu
                                          decision <- readNumber
                                          
                                          putStrLn "Enter the row index: "
                                          row <- readMaxNumber (getRows spreadsheet)
                                          putStrLn "Enter the column index: "
                                          col <- readMaxNumber (getCols spreadsheet)
                                          
                                          if decision == 0 then
                                            do
                                               return (spreadsheet)
                                          else if decision /= 1 && decision /= 2 && decision /= 3 then
                                            do 
                                               putStrLn "Incorrect option."
                                               return (spreadsheet)
                                          else 
                                            do 
                                               list <- readFunCells spreadsheet
                                               if isEmpty list == False then
                                                 do 
                                                    if decision == 1 then
                                                      do 
                                                         let cellVal = Sum list                                                      
                                                         return (insertValue spreadsheet (row - 1) (col - 1) cellVal)
                                                    else if decision == 2 then
                                                      do
                                                         let cellVal = Prod list                                                      
                                                         return (insertValue spreadsheet (row - 1) (col - 1) cellVal)
                                                    else
                                                      do 
                                                         let cellVal = Avg list                                                      
                                                         return (insertValue spreadsheet (row - 1) (col - 1) cellVal)
                                               else
                                                 do
                                                    return (spreadsheet)
                                                                                              
insertValueIntoSpreadsheetMenu = do
                                    putStrLn "Please choose one of allowable options:"
                                    putStrLn "1 - Insert number or text"
                                    putStrLn "2 - Insert function (Sum, Prod, Avg)"
                                    putStrLn "0 - Cancel"

insertValueIntoSpreadsheet spreadsheet = do
                                            insertValueIntoSpreadsheetMenu
                                            decision <- readNumber
                                            
                                            if decision == 1 then
                                              do
                                                 result <- insertSimpleValueIntoSpreadsheet spreadsheet
                                                 return (result)
                                            else if decision == 2 then
                                              do
                                                 result <- insertFunIntoSpreadsheet spreadsheet
                                                 return (result)
                                            else if decision == 0 then
                                              do
                                                 return (spreadsheet)
                                            else
                                              do
                                                 putStrLn "Incorrect option."
                                                 return (spreadsheet)                                                 
                                                 
displayMenu spreadsheet = do
                             putStrLn "Main menu. Please choose one of allowable options:"
                             putStrLn "1 - Create new spreadsheet"
                             putStrLn "2 - Load spreadsheet"
                                              
                             if isEmpty spreadsheet == False then
                               do
                                  putStrLn "3 - Save spreadsheet"
                                  putStrLn "4 - Modify spreadsheet"                                 
                                  putStrLn "5 - Enter a value into a cell"
                                  putStrLn "6 - Show spreadsheet"
                                  return (0)
                             else
                               return (0)
                                    
                             putStrLn "0 - Quit"
                             return (0)                             

exit = exitWith ExitSuccess